package com.wiscamp.ninechapters.problems.infrastructure.repositories;

import com.wiscamp.ninechapters.problems.domain.models.types.QuestionType;
import com.wiscamp.ninechapters.problems.domain.repositories.QuestionTypeRepository;
import com.wiscamp.ninechapters.problems.infrastructure.converters.QuestionTypeConverter;
import com.wiscamp.ninechapters.problems.infrastructure.mappers.types.QuestionTypeMapper;
import com.wiscamp.ninechapters.problems.infrastructure.mappers.types.QuestionTypeViewMapper;
import com.wiscamp.ninechapters.problems.infrastructure.po.types.QuestionTypePO;
import cube.ddd.aspect.HandleDataException;
import cube.ddd.domain.BaseRepository;
import cube.ddd.utils.PersistenceUtils;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Repository;

import java.util.Collection;

@Repository
public class QuestionTypeRepositoryImpl extends BaseRepository implements QuestionTypeRepository {
    private final QuestionTypeMapper questionTypeMapper;

    private final QuestionTypeViewMapper questionTypeViewMapper;

    public QuestionTypeRepositoryImpl(QuestionTypeMapper questionTypeMapper, QuestionTypeViewMapper questionTypeViewMapper) {
        this.questionTypeMapper = questionTypeMapper;
        this.questionTypeViewMapper = questionTypeViewMapper;
    }

    //region QuestionType
    @HandleDataException
    public QuestionTypePO getQuestionTypePO(long typeId) {
        return PersistenceUtils.findById(typeId, questionTypeMapper::findById);
    }

    @HandleDataException
    public QuestionType getQuestionType(long typeId) {
        return PersistenceUtils.findEntityById(typeId, questionTypeViewMapper::findById,
                QuestionTypeConverter.Instance::toQuestionTypeByView);
    }

    @HandleDataException
    public QuestionType getQuestionTypeByCode(@NotBlank String typeCode) {
        return PersistenceUtils.getEntityByText(typeCode, questionTypeViewMapper::findByTypeCode,
                QuestionTypeConverter.Instance::toQuestionTypeByView);
    }

    @HandleDataException
    public Collection<QuestionType> getQuestionTypesByName(@NotBlank String typeName) {
        return PersistenceUtils.getEntitiesByText(typeName, questionTypeViewMapper::findListByTypeName,
                QuestionTypeConverter.Instance::toQuestionTypeByView);
    }

    @HandleDataException
    public Collection<QuestionType> getAvailableQuestionTypes() {
        return PersistenceUtils.getEntities(questionTypeViewMapper::findListByAvailable,
                QuestionTypeConverter.Instance::toQuestionTypeByView);
    }

    @HandleDataException
    public Collection<QuestionType> getQuestionTypesByIds(@NotEmpty Collection<Long> questionIds) {
        return PersistenceUtils.getEntitiesByIds(questionIds, questionTypeViewMapper::findAllById,
                QuestionTypeConverter.Instance::toQuestionTypeByView);
    }

    /**
     * Creates or updates a question type
     *
     * @param questionType
     * @return
     */
    @HandleDataException
    public QuestionType saveQuestionType(@NotNull QuestionType questionType) {
        var newId = questionType.getTypeId();
        if (questionType.getTypeId() <= 0) {
            var newType = PersistenceUtils.createEntity(questionType, questionTypeMapper::saveAndFlush,
                    QuestionTypeConverter.Instance::toQuestionTypePO, QuestionTypeConverter.Instance::toQuestionType);
            newId = newType.getTypeId();
        } else {
            var existedPO = getQuestionTypePO(questionType.getTypeId());
            if (existedPO == null) existedPO = new QuestionTypePO();
            PersistenceUtils.updateEntity(questionType, existedPO, questionTypeMapper::saveAndFlush,
                    QuestionTypeConverter.Instance::toQuestionTypePO, QuestionTypeConverter.Instance::toQuestionType);
        }
        return getQuestionType(newId);
    }

    //endregion
}
